/*******************************************************************************
 * Copyright (c) 2013 Zero Square LLC.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Zero Square LLC. Version 1
 * which accompanies this distribution
 ******************************************************************************/
package com.zsqr.dashboard.commons.dao;

import java.io.Serializable;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.springframework.transaction.annotation.Transactional;

import com.zsqr.dashboard.domain.UserEntity;

/**
 * Provide generic common implementation of GenericDao interface persistence method
 * Extend this abstract class to implement DAO
 * @author Saurabh
 *
 */
@Transactional
public abstract class GenericJpaDao <T, ID extends Serializable> implements GenericDao<T,ID>{
	//Define entity type class variable
	private Class<T> persistenceClass;
	
	//Define entity manger from java persistence package
	private EntityManager entityManager;
	
	//Create Public constructor
	public GenericJpaDao(Class<T> persistenceClass){
		this.persistenceClass = persistenceClass;
		
	}

	//Protected for derived class
	protected EntityManager getEntityManager() {
		return entityManager;
	}

	//At start of application it needs to get hibernate entity manager annotation  
	@PersistenceContext
	public void setEntityManager(EntityManager entityManager) {
		this.entityManager = entityManager;
	}
	
	//Generated only getter as value will be set by constructor
	public Class<T> getPersistenceClass() {
		return persistenceClass;
	}
	
	@Transactional(readOnly=true)
	public T findById (ID id){
		T entity = (T) getEntityManager().find(getPersistenceClass(), id);
		return entity;		
	}
	
	//here we are putting query using class name and hibernate will 
	//pick table name from entity class
	@SuppressWarnings ("unchecked")
	@Transactional (readOnly=true)
	public List<T> findAll(){
		return getEntityManager().createQuery("select x from " + getPersistenceClass().getSimpleName()+ "x")
		.getResultList();
	}
	
	public T save (T entity){
		getEntityManager().persist(entity);
		return entity;
	}
	
	public T update (T entity){
		getEntityManager().merge(entity);
		return entity;
	}
	
	public void delete (T entity){
		if(UserEntity.class.isAssignableFrom(persistenceClass)){
			getEntityManager().remove(getEntityManager().getReference
					(entity.getClass(),((UserEntity)entity).getUserName()));
		}else{
			entity = getEntityManager().merge(entity);
			getEntityManager().remove(entity);
		}
	}
	
	public void flush(){
		getEntityManager().flush();
	}
}
